iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 29
1
DevOps

Git 其然,Git 其所以然系列 第 29

Git Working Tree

  • 分享至 

  • xImage
  •  
# Outline
一、前言
二、概念
三、實驗
四、結語
A、延伸思考

# TL;DR

一、前言

在〈Repository〉有提到 Repository 就是指 .git 本身,我們平時開發工作空間就是指 Working Directory,但更精確的說,是一個 Working Tree。Working Tree 是相依於一個 Repository 的,畢竟我們是從「倉儲」裡面搬檔案出來的,那是否有個可能事,我們能同時擁有多個 Working Tree?

或許我們都曾遇過類似的情境,我們在 A branch 進行開發,這時候突然想要參照另一個 branch、tag 或是 commit 版本的程式碼時該怎麼辦?或是我們因為一些緣故,不得不一直在兩個 branch 頻繁切換來開發?或許這時候我們都會很希望能同時開兩個 branch,也就是同時擁有多個 Working Tree。

幸運的是,Git 還真做得到。

二、概念

在一開始或許我們可以先思考,要多一個獨立的 Working Tree,那在 Git Repository 的哪些檔案或是目錄也必須自己有獨立的?

基本上儲存在 Repository 的 Git Objects 和 Git Reference 都是可以共用的。那麼我們就是指向這些的資訊是要獨立的,也就是所謂的 HEAD,透過獨立的 HEAD 讓我們的 Working Tree 可以有自己當前位置的參考,也就是可以和原本的 Working Directory 有不一樣的當前 Branch 或是 Commit 參考。

另位需要獨立的就是 Staging Area 了,也就是所謂的 index,讓我們準備 commit 的暫存索引是和原本的 Working Directory 是分開的,才不會錯亂。

至於實際 Git 是獨立了哪些資訊,是怎麼讓 Working Tree 獨立的,就讓我們在下面的實驗解答吧!

三、實驗

# Command Synopsis: git-init 
# Reference: https://git-scm.com/docs/git-init
git worktree add [OPTIONS] <path> [<commit-ish>]

Create <path> and checkout <commit-ish> into it. The new working directory is linked to the current repository, sharing everything except working directory specific files such as HEAD, index, etc.

OPTIONS
	-f
  --detach
  --checkout
  --lock
  -b <new-branch>
  -B

首先,先透過 git-worktree-add 指令去建立一個新的 Working Tree:

# Location: ~/how-git-works/lab
$ git worktree add ../lab-working-tree feature/ironman-git-tree
Preparing worktree (resetting branch 'feature/ironman-git-tree'; was at e2349d5)
HEAD is now at 81e9535 F

在上一層目錄透過 ls 指令檢視,的確多了一個 lab-working-tree 的目錄:

# Location: ~/how-git-works/
$ ls -l
drwxr-xr-x  4 ironman  ironman  128  9 25 01:38 dot-git
drwxr-xr-x  4 ironman  ironman  128 10 15 14:25 lab
drwxr-xr-x  4 ironman  ironman  128 10 15 19:15 lab-working-tree

若是在該層目錄透過 ls 指令檢視,會驚奇的發現,.git 不是一個目錄,而是一個檔案:

# Location: ~/how-git-works/lab-working-tree
$ ls -l
-rw-r--r--  1 ironman  ironman   91 10 15 19:15 .git
-rw-r--r--  1 ironman  ironman   20 10 15 19:15 README.md

這時候我們嘗試用 cat 去顯示這個檔案的內容:

# Location: ~/how-git-works/lab-working-tree
$ cat .git
gitdir: /Users/ironman/how-git-works/.git/worktrees/lab-working-tree

這時候我們暸解到這裡的 .git 其實也是某種 reference,只不過和前面提到的 Git Reference 不一樣,他指向的不是一個 Git Commit Object,而是一個存放 Working Tree 資料的目錄,而這個目錄正位於我們原本 Repository 的 .git/worktrees 目錄底下。

再次透過透過 ls 指令檢視這個目錄:

# Location: ~/how-git-works/lab-working-tree
$ ls -l
total 40
-rw-r--r--  1 ironman  ironman   41 10 15 19:15 HEAD
-rw-r--r--  1 ironman  ironman   41 10 15 19:15 ORIG_HEAD
-rw-r--r--  1 ironman  ironman    6 10 15 19:15 commondir
-rw-r--r--  1 ironman  ironman   66 10 15 19:15 gitdir
-rw-r--r--  1 ironman  ironman  137 10 15 19:15 index
drwxr-xr-x  3 ironman  ironman   96 10 15 19:15 logs

一一將這些檔案透過 cat 指令顯示出來:

$ cat HEAD
ref: refs/heads/feature/ironman-git-tree

$ cat ORIG_HEAD
81e953569c9c0740ddfadf16e1318451273335c1

$ cat commondir
../..

$ cat gitdir
/Users/ironman/how-git-works/lab-working-tree/.git

$ cat index
# 這邊會是亂數,因為 index 不是純文字檔案

HEADORIG_HEAD 我們並不陌生,分別是當前 Working Tree 指向的位置以及進行危險動作前的位置。那麼 commondirgitdir是什麼呢?透過顯示的內容來看,可以得知 commondir 其實就是指向原本的 Repository .git 本身,讓我們知道去哪裡索取共用的資料。而 gitdir 就是指向 Working Tree 的 .git 路徑,讓我們 Git 可以隨時追蹤 Working Tree 的狀態,像是這個目錄是不是還在等等。

透過這一系列的實驗,我們大致就暸解 Git 是怎麼建立一個 Working Tree、有哪些資訊是和原本的 Working Directory 獨立的、又怎麼儲存了。


上一篇
Git Repository
下一篇
How Git Works:目錄
系列文
Git 其然,Git 其所以然31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言